home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / quake.zip / HIPGRAPL.ZIP / WEAPONS.QC < prev    next >
Text File  |  1997-04-09  |  55KB  |  2,356 lines

  1. /*
  2. */
  3. //JIM
  4. void( vector pos ) placebullethole;
  5. void (entity targ, entity inflictor, entity attacker, float damage) T_Damage;
  6. void () player_run;
  7. void(entity bomb, entity attacker, float rad, entity ignore) T_RadiusDamage;
  8. void(vector org, vector vel, float damage) SpawnBlood;
  9. void() SuperDamageSound;
  10.  
  11. //MED 10/18/96
  12. void(float damage) spawn_touchblood;
  13. /*
  14. ================
  15. HIPNOTIC WEAPONS
  16. ================
  17. */
  18. void() HIP_LaserTouch =
  19. {
  20.     local vector org;
  21.    local vector spot1,spot2;
  22.    local vector oldvel;
  23.    local float mag;
  24.    local float r;
  25.  
  26.    self.owner = world;
  27.    self.cnt = self.cnt + 1;
  28.    if (pointcontents(self.origin) == CONTENT_SKY)
  29.     {
  30.         remove(self);
  31.         return;
  32.     }
  33.    oldvel = normalize(self.old_velocity);
  34.    spot1 = self.origin - (16*oldvel);
  35.    spot2 = self.origin + (16*oldvel);
  36.    traceline (spot1, spot2, FALSE, self);  // see through other monsters
  37.    self.origin = trace_endpos;
  38.  
  39.    org = self.origin;
  40.  
  41.     if (other.health)
  42.       {
  43.       if (self.lastvictim == other)
  44.          {
  45.          self.dmg = self.dmg / 2;
  46.          }
  47.       spawn_touchblood (self.dmg);
  48.       T_Damage (other, self, self.lastvictim, self.dmg);
  49.       }
  50.    else if ((self.cnt == 3) || (random()<0.15))
  51.       {
  52.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  53.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  54.         WriteCoord (MSG_BROADCAST, org_x);
  55.         WriteCoord (MSG_BROADCAST, org_y);
  56.         WriteCoord (MSG_BROADCAST, org_z);
  57.       }
  58.    else
  59.       {
  60. //      self.dmg = 0.66 * self.dmg;
  61.       self.dmg = 0.9 * self.dmg;
  62. //      self.speed = 0.95 * self.speed;
  63.       self.velocity = oldvel+(2*trace_plane_normal);
  64.       self.velocity = normalize(self.velocity);
  65.       self.velocity = self.speed * self.velocity;
  66.       self.old_velocity = self.velocity;
  67.       if (self.flags & FL_ONGROUND)
  68.          self.flags = self.flags - FL_ONGROUND;
  69.       r = random();
  70.       sound (self, CHAN_WEAPON, "hipweap/laserric.wav", 1, ATTN_STATIC);
  71. /*
  72.       if (r<0.33)
  73.          sound (self, CHAN_WEAPON, "weapons/ric1.wav", 1, ATTN_STATIC);
  74.       else if (r<0.66)
  75.          sound (self, CHAN_WEAPON, "weapons/ric2.wav", 1, ATTN_STATIC);
  76.       else
  77.          sound (self, CHAN_WEAPON, "weapons/ric3.wav", 1, ATTN_STATIC);
  78. */
  79.       return;
  80.       }
  81.    sound (self, CHAN_WEAPON, "enforcer/enfstop.wav", 1, ATTN_STATIC);
  82.    remove(self);
  83.  
  84. };
  85. void() HIP_LaserThink =
  86.    {
  87.    local float delta;
  88.  
  89.  
  90.    if (time>self.attack_finished)
  91.       {
  92.       remove(self);
  93.       return;
  94.       }
  95.    if (self.flags & FL_ONGROUND)
  96.       self.flags = self.flags - FL_ONGROUND;
  97.    self.velocity = self.old_velocity;
  98.    self.angles = vectoangles(self.velocity);
  99.  
  100.    self.nextthink = time+0.1;
  101.    };
  102.  
  103. void(vector org, vector vec, float light) HIP_LaunchLaser =
  104. {
  105. //   sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
  106.    sound (self ,CHAN_WEAPON, "hipweap/laserg.wav", 1, ATTN_NORM);
  107.  
  108.    vec = normalize(vec);
  109.  
  110.     newmis = spawn();
  111.    newmis.owner = self;
  112.    newmis.classname = "hiplaser";
  113.    newmis.lastvictim = self;
  114.    newmis.movetype = MOVETYPE_FLYMISSILE;
  115.    newmis.solid = SOLID_BBOX;
  116.    if (light)
  117.       newmis.effects = EF_DIMLIGHT;
  118.  
  119.    setmodel (newmis, "progs/lasrspik.mdl");
  120.     setsize (newmis, '0 0 0', '0 0 0');
  121.  
  122.     setorigin (newmis, org);
  123.  
  124.    newmis.speed = 1000;
  125.    newmis.dmg = 18;
  126.  
  127.    newmis.velocity = vec * newmis.speed;
  128.    newmis.old_velocity = newmis.velocity;
  129.    newmis.angles = vectoangles(newmis.velocity);
  130.    newmis.avelocity = '0 0 400';
  131.  
  132.    newmis.nextthink = time;
  133.    newmis.attack_finished = time + 5;
  134.    newmis.think = HIP_LaserThink;
  135.    newmis.touch = HIP_LaserTouch;
  136.    newmis.count = 0;
  137.  
  138. };
  139.  
  140. /*
  141. =================
  142. HIP_FireLaser
  143. =================
  144. */
  145. void(float stat) HIP_FireLaser =
  146.    {
  147.     local vector org;
  148.    local vector dir;
  149.    local vector out;
  150.    local float ofs;
  151.    local float aofs;
  152.  
  153.    if (!self.button0)
  154.       {
  155.       player_run ();
  156.       return;
  157.       }
  158.    if (self.ammo_cells < 1)
  159.       {
  160.         self.weapon = W_BestWeapon ();
  161.         W_SetCurrentAmmo ();
  162.         return;
  163.       }
  164.    SuperDamageSound();
  165.    self.effects = self.effects | EF_MUZZLEFLASH;
  166.    makevectors (self.v_angle);
  167.  
  168.    ofs = 6;
  169.    out = v_forward;
  170.    out_z = 0;
  171.    out = normalize(out);
  172.    org = self.origin + ((12-ofs) * v_up) + (12*out);
  173. //   org = self.origin + (1*v_forward);
  174.    dir = aim (self, 1000);
  175.    aofs = ofs * 0.707;
  176.    if (stat == 0)
  177.       {
  178.       self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  179.       org = org + (aofs*v_right);
  180.       org = org - (aofs*v_up);
  181.       HIP_LaunchLaser(org, dir, 0);
  182.       org = org - (2*aofs*v_right);
  183.       HIP_LaunchLaser(org, dir, 0);
  184.       }
  185.    else if (stat == 1)
  186.       {
  187.       self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  188.       org = org + (ofs*v_up);
  189.       if (random()<0.1)
  190.          {
  191.          HIP_LaunchLaser(org, dir, 1);
  192.          newmis.dmg = 25;
  193.          }
  194.       else
  195.          HIP_LaunchLaser(org, dir, 0);
  196.       }
  197.    self.punchangle_x = -1;
  198.    };
  199.  
  200. /*
  201. =================
  202. HIP_HammerDamage
  203. =================
  204. */
  205. void(vector p1, vector p2, entity from, float damage) HIP_HammerDamage =
  206. {
  207.     local entity        e1, e2;
  208.     local vector        f;
  209.  
  210.     f = p2 - p1;
  211.     normalize (f);
  212.     f_x = 0 - f_y;
  213.     f_y = f_x;
  214.     f_z = 0;
  215.     f = f*16;
  216.  
  217.     e1 = e2 = world;
  218.  
  219.     traceline (p1, p2, FALSE, self);
  220. //JIM
  221.     if (trace_ent.takedamage && !trace_ent.wetsuit_finished )
  222.     {
  223.         particle (trace_endpos, '0 0 100', 225, damage*4);
  224.         T_Damage (trace_ent, from, from, damage);
  225.         if (self.classname == "player")
  226.         {
  227.             if (other.classname == "player")
  228.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  229.         }
  230.     }
  231.     e1 = trace_ent;
  232.  
  233.     traceline (p1 + f, p2 + f, FALSE, self);
  234. //JIM
  235.     if (trace_ent != e1 && trace_ent.takedamage &&
  236.         !trace_ent.wetsuit_finished )
  237.     {
  238.         particle (trace_endpos, '0 0 100', 225, damage*4);
  239.         T_Damage (trace_ent, from, from, damage);
  240.     }
  241.     e2 = trace_ent;
  242.  
  243.     traceline (p1 - f, p2 - f, FALSE, self);
  244. //JIM
  245.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage &&
  246.         !trace_ent.wetsuit_finished )
  247.     {
  248.         particle (trace_endpos, '0 0 100', 225, damage*4);
  249.         T_Damage (trace_ent, from, from, damage);
  250.     }
  251. };
  252.  
  253. /*
  254. void() HIP_DiversionLightningThink =
  255.    {
  256.    local vector   org,end;
  257.  
  258.    if (time > self.delay)
  259.       {
  260.       remove(self);
  261.       return;
  262.       }
  263.  
  264.    makevectors(self.v_angle);
  265.    org = self.origin;
  266.    end = org + v_forward*200;
  267. //   end = end + (((200*random()) - 100) * v_up);
  268.    end = end + (((400*random()) - 200) * v_right);
  269.  
  270.    traceline (org, end, TRUE, self);
  271.  
  272.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  273.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  274.     WriteEntity (MSG_BROADCAST, self);
  275.     WriteCoord (MSG_BROADCAST, org_x);
  276.     WriteCoord (MSG_BROADCAST, org_y);
  277.     WriteCoord (MSG_BROADCAST, org_z);
  278.    WriteCoord (MSG_BROADCAST, trace_endpos_x);
  279.    WriteCoord (MSG_BROADCAST, trace_endpos_y);
  280.    WriteCoord (MSG_BROADCAST, trace_endpos_z);
  281.  
  282.    self.nextthink = time + 0.1;
  283.    };
  284. */
  285.  
  286. //void(entity prev, entity owner, float dst) HIP_SpawnMjolnirLightning;
  287. void() HIP_LightningThink =
  288.    {
  289.    local vector org;
  290.    local vector dst;
  291.    local entity head;
  292.    local entity selected;
  293.    local float cur_dist;
  294.    local float head_dist;
  295.    local vector vec;
  296.    local float dot;
  297.    local float oldstate;
  298.    local float dam;
  299.  
  300.  
  301.    if (time > self.delay)
  302.       {
  303.       if (self.enemy != world)
  304.          self.enemy.struck_by_mjolnir = 0;
  305.       remove(self);
  306.       return;
  307.       }
  308.    oldstate = self.state;
  309.    if (self.state==0)
  310.       {
  311.       // look in our immediate vicinity
  312.       self.enemy = world;
  313.       selected = world;
  314.       cur_dist = self.distance;
  315.       head = findradius(self.owner.origin, self.distance);
  316.       while(head)
  317.          {
  318.          if(!(head.flags & FL_NOTARGET) && ((head.flags & FL_MONSTER) || (head.flags & FL_CLIENT)))
  319.             {
  320. //            if (visible(head) && (head!=self.owner.owner) && (head.health>0))
  321.             if ((visible(head)) && (head!=self.owner.owner) && (head.health>0))
  322.                {
  323.                head_dist = vlen(head.origin - self.lastvictim.origin);
  324.                if ((head_dist<cur_dist) && (head.struck_by_mjolnir==0))
  325.                   {
  326.                   selected = head;
  327.                   cur_dist = head_dist;
  328.                   }
  329.                }
  330.             }
  331.          head = head.chain;
  332.          }
  333.       if (selected != world)
  334.          {
  335.          self.state = 1;
  336.          self.enemy = selected;
  337.          self.enemy.struck_by_mjolnir = 1;
  338.          }
  339.       else
  340.          {
  341.          local vector   org,end;
  342.  
  343.          makevectors(self.v_angle);
  344.          org = self.owner.origin;
  345.          end = org + v_forward*200;
  346.          end = end + (((400*random()) - 200) * v_right);
  347.  
  348.          traceline (org, end, TRUE, self);
  349.  
  350.          WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  351.          WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  352.          WriteEntity (MSG_BROADCAST, self);
  353.          WriteCoord (MSG_BROADCAST, org_x);
  354.          WriteCoord (MSG_BROADCAST, org_y);
  355.          WriteCoord (MSG_BROADCAST, org_z);
  356.          WriteCoord (MSG_BROADCAST, trace_endpos_x);
  357.          WriteCoord (MSG_BROADCAST, trace_endpos_y);
  358.          WriteCoord (MSG_BROADCAST, trace_endpos_z);
  359.  
  360.          self.nextthink = time + 0.1;
  361. //         self.think = HIP_DiversionLightningThink;
  362. //         self.nextthink = time;
  363. //         self.delay = time + 0.30;
  364. //         self.origin = self.owner.origin;
  365. //         self.think();
  366.          return;
  367.          }
  368.       }
  369.    org = self.lastvictim.origin;
  370.    dst = self.enemy.absmin + 0.25*(self.enemy.absmax-self.enemy.absmin);
  371.    dst = dst + (random()*0.5*(self.enemy.absmax-self.enemy.absmin));
  372.    traceline (org, dst, TRUE, self.owner.owner);
  373.  
  374.    if (trace_fraction != 1.0 || self.enemy.health<=0)
  375.       {
  376.       self.enemy.struck_by_mjolnir = 0;
  377.       self.state = 0;
  378.       self.nextthink = time + 0.1;
  379.       return;
  380.       }
  381.    WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  382.    WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  383.    WriteEntity (MSG_BROADCAST, self);
  384.    WriteCoord (MSG_BROADCAST, org_x);
  385.    WriteCoord (MSG_BROADCAST, org_y);
  386.    WriteCoord (MSG_BROADCAST, org_z);
  387.    WriteCoord (MSG_BROADCAST, trace_endpos_x);
  388.    WriteCoord (MSG_BROADCAST, trace_endpos_y);
  389.    WriteCoord (MSG_BROADCAST, trace_endpos_z);
  390.    vec = normalize(self.enemy.origin - self.owner.origin);
  391.    dot = vec * self.owner.movedir;
  392.    head = self;
  393.    self = self.owner.owner;
  394.    if (oldstate==0)
  395.       dam = 80;
  396.    else
  397.       dam = 30;
  398.    if (dot>0.3)
  399.       HIP_HammerDamage (org, trace_endpos, self, dam);
  400.    else
  401.       HIP_HammerDamage (org, trace_endpos, self, dam*0.5);
  402.    self = head;
  403.  
  404.    self.nextthink = time + 0.2;
  405.    };
  406.  
  407. void(entity prev, entity own, float dst) HIP_SpawnMjolnirLightning =
  408.    {
  409.    local entity light;
  410.    // spawn actual lightning
  411.    light = spawn();
  412.    light.delay = time + 0.8;
  413.    light.state = 0;
  414.    light.lastvictim = prev;
  415.    light.distance = dst;
  416.    light.owner = own;
  417.    light.v_angle = self.angles;
  418.    light.v_angle_x = 0;
  419.    light.v_angle_z = 0;
  420.    light.origin = own.origin;
  421.    light.think = HIP_LightningThink;
  422.    light.nextthink = time;
  423.    };
  424.  
  425. void() HIP_SpawnMjolnirBase =
  426.    {
  427.    local entity light;
  428.    // spawn lightning base
  429.    light = spawn();
  430. //   light.origin = self.origin - '0 0 24' + (32*v_forward);
  431.    light.origin = trace_endpos;
  432.    light.flags = 0;
  433.    light.owner = self;
  434.    light.struck_by_mjolnir = 1;
  435.    light.think = SUB_Remove;
  436.    light.nextthink = time + 1;
  437.    sound (light, CHAN_AUTO, "hipweap/mjolslap.wav", 1, ATTN_NORM);
  438.    sound (light, CHAN_WEAPON, "hipweap/mjolhit.wav", 1, ATTN_NORM);
  439.    makevectors(self.v_angle);
  440.    light.movedir = v_forward;
  441.    HIP_SpawnMjolnirLightning( light, light, 350 );
  442.    HIP_SpawnMjolnirLightning( light, light, 350 );
  443.    HIP_SpawnMjolnirLightning( light, light, 350 );
  444.    HIP_SpawnMjolnirLightning( light, light, 350 );
  445.    };
  446.  
  447. void() HIP_FireMjolnirLightning =
  448.    {
  449.    local vector   org;
  450.     local    float        cells;
  451.  
  452. // explode if under water
  453.     if (self.waterlevel > 1)
  454.     {
  455.         cells = self.ammo_cells;
  456.         self.ammo_cells = 0;
  457.       discharged = 1;
  458.         T_RadiusDamage (self, self, 35*cells, world);
  459.       discharged = 0;
  460.         W_SetCurrentAmmo ();
  461.         return;
  462.     }
  463.  
  464. //   if (self.t_width < time)
  465. //   {
  466. //      sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  467. //      self.t_width = time + 0.6;
  468. //   }
  469. //   self.punchangle_x = 12;
  470.  
  471.    self.currentammo = self.ammo_cells = self.ammo_cells - 15;
  472.  
  473.    HIP_SpawnMjolnirBase();
  474.    };
  475.  
  476. void() HIP_FireMjolnir =
  477.    {
  478.    local vector   org;
  479.     local    float        cells;
  480.    local float    damage;
  481.    local vector   source;
  482.    local vector   ang;
  483.  
  484.  
  485.    self.attack_finished = time + 0.4;
  486.    source = self.origin + '0 0 16';
  487. //   ang = self.angles;
  488. //   ang_x = 0;
  489. //   ang_y = 0;
  490.    makevectors(self.v_angle);
  491.    traceline (source, source + v_forward*32, FALSE, self);
  492.    if (trace_fraction == 1.0 && (self.ammo_cells >= 15))
  493.       {
  494.       source = source + v_forward*32;
  495.       traceline (source , source - v_up*50, FALSE, self);
  496. //      dprint("fraction = ");
  497. //      dprint(ftos(trace_fraction));
  498. //      dprint("\n");
  499.       if (trace_fraction > 0.3 && trace_fraction< 1.0)
  500.          {
  501.          HIP_FireMjolnirLightning();
  502.          self.attack_finished = time + 1.5;
  503.          return;
  504.          }
  505.       }
  506.    org = trace_endpos - v_forward*4;
  507.  
  508.    if (trace_ent.takedamage)
  509.       {
  510.       damage = 50;
  511.       if (trace_ent.classname == "monster_zombie")
  512.          damage = 70;
  513.       trace_ent.axhitme = 1;
  514.       SpawnBlood (org, v_forward, damage);
  515.       T_Damage (trace_ent, self, self, damage);
  516.       }
  517.    else
  518.       {  // hit wall
  519.       if (trace_fraction != 1.0)
  520.          {
  521. //         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  522.          sound (self, CHAN_WEAPON, "hipweap/mjoltink.wav", 1, ATTN_NORM);
  523.          WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  524.          WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  525.          WriteCoord (MSG_BROADCAST, org_x);
  526.          WriteCoord (MSG_BROADCAST, org_y);
  527.          WriteCoord (MSG_BROADCAST, org_z);
  528.          }
  529.       else
  530.          {
  531.          sound (self, CHAN_WEAPON, "knight/sword1.wav", 1, ATTN_NORM);
  532.          }
  533.       }
  534.    self.attack_finished = time + 0.4;
  535.  
  536.    };
  537.  
  538. // called by worldspawn
  539. void() W_Precache =
  540. {
  541.     precache_sound ("weapons/r_exp3.wav");    // new rocket explosion
  542.     precache_sound ("weapons/rocket1i.wav");    // spike gun
  543.     precache_sound ("weapons/sgun1.wav");
  544.     precache_sound ("weapons/guncock.wav");    // player shotgun
  545.     precache_sound ("weapons/ric1.wav");    // ricochet (used in c code)
  546.     precache_sound ("weapons/ric2.wav");    // ricochet (used in c code)
  547.     precache_sound ("weapons/ric3.wav");    // ricochet (used in c code)
  548.     precache_sound ("weapons/spike2.wav");    // super spikes
  549.     precache_sound ("weapons/tink1.wav");    // spikes tink (used in c code)
  550.     precache_sound ("weapons/grenade.wav");    // grenade launcher
  551.     precache_sound ("weapons/bounce.wav");        // grenade bounce
  552.     precache_sound ("weapons/shotgn2.wav");    // super shotgun
  553.  
  554. // Grapple:  Precache grapple sounds too!
  555.         precache_sound2 ("blob/land1.wav");     // chain go splorch!
  556.         precache_sound ("items/protect3.wav");  // Heheh... fix for cheats
  557.         precache_sound ("items/damage3.wav");   // This too
  558.         precache_sound ("weapons/chain1.wav");  // chain cranking out
  559.         precache_sound ("weapons/chain2.wav");  // chain cranking in
  560.         precache_sound ("weapons/chain3.wav");  // chain swaying in breeze
  561.         precache_sound ("weapons/gotcha.wav");  // a lame programmer trying
  562.                                                 //   to cop a 'tude
  563.         precache_sound ("weapons/thankyou.wav"); // Thank you for playing!
  564.                                                  //   See you in hell!
  565.         precache_sound ("weapons/bounce2.wav");  // chain release
  566.  
  567. //MED
  568.    precache_sound ("enforcer/enfstop.wav");   // laser cannon
  569. //MED 11/06/96
  570.    precache_sound ("knight/sword1.wav");   // laser cannon
  571.    precache_sound ("hipweap/laserg.wav");   // laser cannon
  572.    precache_sound ("hipweap/laserric.wav");   // laser cannon ricochet
  573.    precache_sound ("hipweap/proxwarn.wav");   // proximity bomb
  574.    precache_sound ("hipweap/proxbomb.wav");   // proximity bomb
  575. //MED 11/19/96
  576.    precache_sound ("hipweap/mjolhit.wav");   // mjolnir
  577.    precache_sound ("hipweap/mjolslap.wav");   // mjolnir
  578.    precache_sound ("hipweap/mjoltink.wav");   // mjolnir
  579. };
  580.  
  581. float() crandom =
  582. {
  583.     return 2*(random() - 0.5);
  584. };
  585.  
  586. /*
  587. ================
  588. W_FireAxe
  589. ================
  590. */
  591. void() W_FireAxe =
  592. {
  593.     local    vector    source;
  594.     local    vector    org;
  595.  
  596.    makevectors (self.v_angle);
  597.    source = self.origin + '0 0 16';
  598.     traceline (source, source + v_forward*64, FALSE, self);
  599.     if (trace_fraction == 1.0)
  600.         return;
  601.  
  602.     org = trace_endpos - v_forward*4;
  603.  
  604.     if (trace_ent.takedamage)
  605.     {
  606.         trace_ent.axhitme = 1;
  607.         SpawnBlood (org, '0 0 0', 20);
  608.         T_Damage (trace_ent, self, self, 20);
  609.     }
  610.     else
  611.     {    // hit wall
  612.         sound (self, CHAN_WEAPON, "player/axhit2.wav", 1, ATTN_NORM);
  613.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  614.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  615.         WriteCoord (MSG_BROADCAST, org_x);
  616.         WriteCoord (MSG_BROADCAST, org_y);
  617.         WriteCoord (MSG_BROADCAST, org_z);
  618.     }
  619. };
  620.  
  621.  
  622. //============================================================================
  623.  
  624.  
  625. vector() wall_velocity =
  626. {
  627.     local vector    vel;
  628.  
  629.     vel = normalize (self.velocity);
  630.     vel = normalize(vel + v_up*(random()- 0.5) + v_right*(random()- 0.5));
  631.     vel = vel + 2*trace_plane_normal;
  632.     vel = vel * 200;
  633.  
  634.     return vel;
  635. };
  636.  
  637.  
  638. /*
  639. ================
  640. SpawnMeatSpray
  641. ================
  642. */
  643. void(vector org, vector vel) SpawnMeatSpray =
  644. {
  645.     local    entity missile, mpuff;
  646.     local    vector    org;
  647.  
  648.     missile = spawn ();
  649.     missile.owner = self;
  650.     missile.movetype = MOVETYPE_BOUNCE;
  651.     missile.solid = SOLID_NOT;
  652.  
  653.     makevectors (self.angles);
  654.  
  655.     missile.velocity = vel;
  656.     missile.velocity_z = missile.velocity_z + 250 + 50*random();
  657.  
  658.     missile.avelocity = '3000 1000 2000';
  659.  
  660. // set missile duration
  661.     missile.nextthink = time + 1;
  662.     missile.think = SUB_Remove;
  663.  
  664.     setmodel (missile, "progs/zom_gib.mdl");
  665.     setsize (missile, '0 0 0', '0 0 0');
  666.     setorigin (missile, org);
  667. };
  668.  
  669. /*
  670. ================
  671. SpawnBlood
  672. ================
  673. */
  674. void(vector org, vector vel, float damage) SpawnBlood =
  675. {
  676.     particle (org, vel*0.1, 73, damage*2);
  677. };
  678.  
  679. /*
  680. ================
  681. spawn_touchblood
  682. ================
  683. */
  684. void(float damage) spawn_touchblood =
  685. {
  686.     local vector    vel;
  687.  
  688.     vel = wall_velocity () * 0.2;
  689.     SpawnBlood (self.origin + vel*0.01, vel, damage);
  690. };
  691.  
  692.  
  693. /*
  694. ================
  695. SpawnChunk
  696. ================
  697. */
  698. void(vector org, vector vel) SpawnChunk =
  699. {
  700.     particle (org, vel*0.02, 0, 10);
  701. };
  702.  
  703. /*
  704. ==============================================================================
  705.  
  706. MULTI-DAMAGE
  707.  
  708. Collects multiple small damages into a single damage
  709.  
  710. ==============================================================================
  711. */
  712.  
  713. entity    multi_ent;
  714. float    multi_damage;
  715.  
  716. void() ClearMultiDamage =
  717. {
  718.     multi_ent = world;
  719.     multi_damage = 0;
  720. };
  721.  
  722. void() ApplyMultiDamage =
  723. {
  724.     if (!multi_ent)
  725.         return;
  726.     T_Damage (multi_ent, self, self, multi_damage);
  727. };
  728.  
  729. void(entity hit, float damage) AddMultiDamage =
  730. {
  731.     if (!hit)
  732.         return;
  733.  
  734.     if (hit != multi_ent)
  735.     {
  736.         ApplyMultiDamage ();
  737.         multi_damage = damage;
  738.         multi_ent = hit;
  739.     }
  740.     else
  741.         multi_damage = multi_damage + damage;
  742. };
  743.  
  744. /*
  745. ==============================================================================
  746.  
  747. BULLETS
  748.  
  749. ==============================================================================
  750. */
  751.  
  752. /*
  753. ================
  754. TraceAttack
  755. ================
  756. */
  757. void(float damage, vector dir) TraceAttack =
  758. {
  759.     local    vector    vel, org;
  760.  
  761.     vel = normalize(dir + v_up*crandom() + v_right*crandom());
  762.     vel = vel + 2*trace_plane_normal;
  763.     vel = vel * 200;
  764.  
  765.     org = trace_endpos - dir*4;
  766.  
  767.     if (trace_ent.takedamage)
  768.     {
  769.         SpawnBlood (org, vel*0.2, damage);
  770.         AddMultiDamage (trace_ent, damage);
  771.     }
  772.     else
  773.     {
  774.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  775.         WriteByte (MSG_BROADCAST, TE_GUNSHOT);
  776.         WriteCoord (MSG_BROADCAST, org_x);
  777.         WriteCoord (MSG_BROADCAST, org_y);
  778.         WriteCoord (MSG_BROADCAST, org_z);
  779.     }
  780. };
  781.  
  782. /*
  783. ================
  784. FireBullets
  785.  
  786. Used by shotgun, super shotgun, and enemy soldier firing
  787. Go to the trouble of combining multiple pellets into a single damage call.
  788. ================
  789. */
  790. void(float shotcount, vector dir, vector spread) FireBullets =
  791. {
  792.     local    vector direction;
  793.     local    vector    src;
  794.    //JIM
  795.    local float bullet;
  796.    bullet = 0;
  797.  
  798.     makevectors(self.v_angle);
  799.  
  800.     src = self.origin + v_forward*10;
  801.     src_z = self.absmin_z + self.size_z * 0.7;
  802.  
  803.     ClearMultiDamage ();
  804.     while (shotcount > 0)
  805.     {
  806.         direction = dir + crandom()*spread_x*v_right + crandom()*spread_y*v_up;
  807.  
  808.         traceline (src, src + direction*2048, FALSE, self);
  809.         if (trace_fraction != 1.0)
  810.          //JIM
  811.          {
  812.             TraceAttack (4, direction);
  813.          if ( ( !bullet ) && ( trace_ent == world ) )
  814.             {
  815.             placebullethole( trace_endpos );
  816.             bullet = 1;
  817.             }
  818.          }
  819.  
  820.         shotcount = shotcount - 1;
  821.     }
  822.     ApplyMultiDamage ();
  823. };
  824.  
  825. /*
  826. ================
  827. W_FireShotgun
  828. ================
  829. */
  830. void() W_FireShotgun =
  831. {
  832.     local vector dir;
  833.  
  834.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
  835.  
  836.     self.punchangle_x = -2;
  837.  
  838.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  839.     dir = aim (self, 100000);
  840.     FireBullets (6, dir, '0.04 0.04 0');
  841. };
  842.  
  843.  
  844. /*
  845. ================
  846. W_FireSuperShotgun
  847. ================
  848. */
  849. void() W_FireSuperShotgun =
  850. {
  851.     local vector dir;
  852.  
  853.     if (self.currentammo == 1)
  854.     {
  855.         W_FireShotgun ();
  856.         return;
  857.     }
  858.  
  859.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
  860.  
  861.     self.punchangle_x = -4;
  862.  
  863.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  864.     dir = aim (self, 100000);
  865.     FireBullets (14, dir, '0.14 0.08 0');
  866. };
  867.  
  868.  
  869. /*
  870. ==============================================================================
  871.  
  872. ROCKETS
  873.  
  874. ==============================================================================
  875. */
  876.  
  877. void()    s_explode1    =    [0,        s_explode2] {};
  878. void()    s_explode2    =    [1,        s_explode3] {};
  879. void()    s_explode3    =    [2,        s_explode4] {};
  880. void()    s_explode4    =    [3,        s_explode5] {};
  881. void()    s_explode5    =    [4,        s_explode6] {};
  882. void()    s_explode6    =    [5,        SUB_Remove] {};
  883.  
  884. void() BecomeExplosion =
  885. {
  886.     self.movetype = MOVETYPE_NONE;
  887.     self.velocity = '0 0 0';
  888.     self.touch = SUB_Null;
  889.     setmodel (self, "progs/s_explod.spr");
  890.     self.solid = SOLID_NOT;
  891.     s_explode1 ();
  892. };
  893.  
  894. void() T_MissileTouch =
  895. {
  896.     local float    damg;
  897.  
  898.     if (other == self.owner)
  899.         return;        // don't explode on owner
  900.  
  901.     if (pointcontents(self.origin) == CONTENT_SKY)
  902.     {
  903.         remove(self);
  904.         return;
  905.     }
  906.  
  907.     damg = 100 + random()*20;
  908.  
  909.     if (other.health)
  910.     {
  911.         if (other.classname == "monster_shambler")
  912.             damg = damg * 0.5;    // mostly immune
  913.         T_Damage (other, self, self.owner, damg );
  914.     }
  915.  
  916.     // don't do radius damage to the other, because all the damage
  917.     // was done in the impact
  918.     T_RadiusDamage (self, self.owner, 120, other);
  919.  
  920. //    sound (self, CHAN_WEAPON, "weapons/r_exp3.wav", 1, ATTN_NORM);
  921.     self.origin = self.origin - 8*normalize(self.velocity);
  922.  
  923.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  924.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  925.     WriteCoord (MSG_BROADCAST, self.origin_x);
  926.     WriteCoord (MSG_BROADCAST, self.origin_y);
  927.     WriteCoord (MSG_BROADCAST, self.origin_z);
  928.  
  929.     BecomeExplosion ();
  930. };
  931.  
  932.  
  933.  
  934. /*
  935. ================
  936. W_FireRocket
  937. ================
  938. */
  939. void() W_FireRocket =
  940. {
  941.     local    entity missile, mpuff;
  942.  
  943.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  944.  
  945.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  946.  
  947.     self.punchangle_x = -2;
  948.  
  949.     missile = spawn ();
  950.     missile.owner = self;
  951.     missile.movetype = MOVETYPE_FLYMISSILE;
  952.     missile.solid = SOLID_BBOX;
  953.     missile.classname = "missile";
  954.  
  955. // set missile speed
  956.  
  957.     makevectors (self.v_angle);
  958.     missile.velocity = aim(self, 1000);
  959.     missile.velocity = missile.velocity * 1000;
  960.     missile.angles = vectoangles(missile.velocity);
  961.  
  962.     missile.touch = T_MissileTouch;
  963.  
  964. // set missile duration
  965.     missile.nextthink = time + 5;
  966.     missile.think = SUB_Remove;
  967.  
  968.     setmodel (missile, "progs/missile.mdl");
  969.     setsize (missile, '0 0 0', '0 0 0');
  970.     setorigin (missile, self.origin + v_forward*8 + '0 0 16');
  971. //MED 11/09/96
  972.    newmis = missile;
  973. };
  974.  
  975. /*
  976. ===============================================================================
  977.  
  978. LIGHTNING
  979.  
  980. ===============================================================================
  981. */
  982.  
  983. /*
  984. =================
  985. LightningDamage
  986. =================
  987. */
  988. void(vector p1, vector p2, entity from, float damage) LightningDamage =
  989. {
  990.     local entity        e1, e2;
  991.     local vector        f;
  992.  
  993.     f = p2 - p1;
  994.     normalize (f);
  995.     f_x = 0 - f_y;
  996.     f_y = f_x;
  997.     f_z = 0;
  998.     f = f*16;
  999.  
  1000.     e1 = e2 = world;
  1001.  
  1002.     traceline (p1, p2, FALSE, self);
  1003. //JIM
  1004.     if (trace_ent.takedamage && !trace_ent.wetsuit_finished )
  1005.     {
  1006.         particle (trace_endpos, '0 0 100', 225, damage*4);
  1007.         T_Damage (trace_ent, from, from, damage);
  1008.         if (self.classname == "player")
  1009.         {
  1010.             if (other.classname == "player")
  1011.                 trace_ent.velocity_z = trace_ent.velocity_z + 400;
  1012.         }
  1013.     }
  1014.     e1 = trace_ent;
  1015.  
  1016.     traceline (p1 + f, p2 + f, FALSE, self);
  1017. //JIM
  1018.     if (trace_ent != e1 && trace_ent.takedamage &&
  1019.         !trace_ent.wetsuit_finished )
  1020.     {
  1021.         particle (trace_endpos, '0 0 100', 225, damage*4);
  1022.         T_Damage (trace_ent, from, from, damage);
  1023.     }
  1024.     e2 = trace_ent;
  1025.  
  1026.     traceline (p1 - f, p2 - f, FALSE, self);
  1027. //JIM
  1028.     if (trace_ent != e1 && trace_ent != e2 && trace_ent.takedamage &&
  1029.         !trace_ent.wetsuit_finished )
  1030.     {
  1031.         particle (trace_endpos, '0 0 100', 225, damage*4);
  1032.         T_Damage (trace_ent, from, from, damage);
  1033.     }
  1034. };
  1035.  
  1036.  
  1037. void() W_FireLightning =
  1038. {
  1039.     local    vector        org;
  1040.     local    float        cells;
  1041.  
  1042.     if (self.ammo_cells < 1)
  1043.     {
  1044.         self.weapon = W_BestWeapon ();
  1045.         W_SetCurrentAmmo ();
  1046.         return;
  1047.     }
  1048.  
  1049. // explode if under water
  1050.     if (self.waterlevel > 1)
  1051.     {
  1052.         cells = self.ammo_cells;
  1053.         self.ammo_cells = 0;
  1054.       //MED 01/05/97 added discharge flag
  1055.       discharged = 1;
  1056.         T_RadiusDamage (self, self, 35*cells, world);
  1057.       discharged = 0;
  1058.         W_SetCurrentAmmo ();
  1059.         return;
  1060.     }
  1061.  
  1062.     if (self.t_width < time)
  1063.     {
  1064.         sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
  1065.         self.t_width = time + 0.6;
  1066.     }
  1067.     self.punchangle_x = -2;
  1068.  
  1069.     self.currentammo = self.ammo_cells = self.ammo_cells - 1;
  1070.  
  1071.     org = self.origin + '0 0 16';
  1072.  
  1073.     traceline (org, org + v_forward*600, TRUE, self);
  1074.  
  1075.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1076.     WriteByte (MSG_BROADCAST, TE_LIGHTNING2);
  1077.     WriteEntity (MSG_BROADCAST, self);
  1078.     WriteCoord (MSG_BROADCAST, org_x);
  1079.     WriteCoord (MSG_BROADCAST, org_y);
  1080.     WriteCoord (MSG_BROADCAST, org_z);
  1081.     WriteCoord (MSG_BROADCAST, trace_endpos_x);
  1082.     WriteCoord (MSG_BROADCAST, trace_endpos_y);
  1083.     WriteCoord (MSG_BROADCAST, trace_endpos_z);
  1084.  
  1085.     LightningDamage (self.origin, trace_endpos + v_forward*4, self, 30);
  1086. };
  1087.  
  1088.  
  1089. //=============================================================================
  1090.  
  1091.  
  1092. void() GrenadeExplode =
  1093. {
  1094.     T_RadiusDamage (self, self.owner, 120, world);
  1095.  
  1096.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1097.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1098.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1099.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1100.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1101.  
  1102.     BecomeExplosion ();
  1103. };
  1104.  
  1105. void() GrenadeTouch =
  1106. {
  1107.     if (other == self.owner)
  1108.         return;        // don't explode on owner
  1109.     if (other.takedamage == DAMAGE_AIM)
  1110.     {
  1111.         GrenadeExplode();
  1112.         return;
  1113.     }
  1114.     sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM);    // bounce sound
  1115.     if (self.velocity == '0 0 0')
  1116.         self.avelocity = '0 0 0';
  1117. };
  1118.  
  1119. /*
  1120. ================
  1121. W_FireGrenade
  1122. ================
  1123. */
  1124. void() W_FireGrenade =
  1125. {
  1126.     local    entity missile, mpuff;
  1127.  
  1128.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  1129.  
  1130.     sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
  1131.  
  1132.     self.punchangle_x = -2;
  1133.  
  1134.     missile = spawn ();
  1135.     missile.owner = self;
  1136.     missile.movetype = MOVETYPE_BOUNCE;
  1137.     missile.solid = SOLID_BBOX;
  1138.     missile.classname = "grenade";
  1139.  
  1140. // set missile speed
  1141.  
  1142.     makevectors (self.v_angle);
  1143.  
  1144.     if (self.v_angle_x)
  1145.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  1146.     else
  1147.     {
  1148.         missile.velocity = aim(self, 10000);
  1149.         missile.velocity = missile.velocity * 600;
  1150.         missile.velocity_z = 200;
  1151.     }
  1152.  
  1153.     missile.avelocity = '300 300 300';
  1154.  
  1155.     missile.angles = vectoangles(missile.velocity);
  1156.  
  1157.     missile.touch = GrenadeTouch;
  1158.  
  1159. // set missile duration
  1160.     missile.nextthink = time + 2.5;
  1161.     missile.think = GrenadeExplode;
  1162.  
  1163.     setmodel (missile, "progs/grenade.mdl");
  1164.     setsize (missile, '0 0 0', '0 0 0');
  1165.     setorigin (missile, self.origin);
  1166. };
  1167.  
  1168. void() ProximityExplode =
  1169. {
  1170.    T_RadiusDamage (self, self.owner, 95, world);
  1171.  
  1172.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1173.     WriteByte (MSG_BROADCAST, TE_EXPLOSION);
  1174.     WriteCoord (MSG_BROADCAST, self.origin_x);
  1175.     WriteCoord (MSG_BROADCAST, self.origin_y);
  1176.     WriteCoord (MSG_BROADCAST, self.origin_z);
  1177.  
  1178.     BecomeExplosion ();
  1179. };
  1180.  
  1181. //MED 10/31/96
  1182. float NumProximityGrenades;
  1183. /*
  1184. ================
  1185. ProximityGrenadeExplode
  1186. ================
  1187. */
  1188. void() ProximityGrenadeExplode =
  1189.    {
  1190.    self.takedamage = DAMAGE_NO;
  1191.    NumProximityGrenades = NumProximityGrenades - 1;
  1192.    self.deathtype = "exploding";
  1193.    self.nextthink = time + 0.1;
  1194.    self.owner = self.lastvictim;
  1195.    self.think = ProximityExplode;
  1196.    };
  1197.  
  1198. /*
  1199. ================
  1200. ProximityGrenadeTouch
  1201. ================
  1202. */
  1203. void() ProximityGrenadeTouch =
  1204.    {
  1205.    if (other == self)
  1206.       return;
  1207.    if (other.classname == self.classname)
  1208.       return;
  1209.    self.movetype = MOVETYPE_TOSS;
  1210.    if (self.state == 1)
  1211.       return;
  1212.    if (vlen(other.velocity) > 0)
  1213.       {
  1214.       ProximityGrenadeExplode();
  1215.       self.think();
  1216.       return;
  1217.       }
  1218.    if (other.takedamage == DAMAGE_AIM)
  1219.       {
  1220.       ProximityGrenadeExplode();
  1221.       self.think();
  1222.       return;
  1223.       }
  1224.    sound (self, CHAN_WEAPON, "weapons/bounce.wav", 1, ATTN_NORM); // bounce sound
  1225.    self.movetype = MOVETYPE_NONE;
  1226.    setsize (self, '-8 -8 -8', '8 8 8');
  1227.    self.state = 1;
  1228.    self.spawnmaster = other;
  1229.    };
  1230.  
  1231. /*
  1232. ================
  1233. ProximityBomb
  1234. ================
  1235. */
  1236. void() ProximityBomb =
  1237.    {
  1238.    local entity   head;
  1239.    local float    blowup;
  1240.  
  1241.    if ((time > self.delay) || (NumProximityGrenades > 15) || (vlen(self.spawnmaster.velocity)>0) )
  1242.       {
  1243.       ProximityGrenadeExplode();
  1244.       self.think();
  1245.       return;
  1246.       }
  1247.    self.owner = world;
  1248.    self.takedamage = DAMAGE_YES;
  1249.    head = findradius(self.origin, 140);
  1250.    blowup = 0;
  1251.  
  1252.    while (head)
  1253.       {
  1254.       if ((head != self) && (head.health > 0) && (head.flags & (FL_CLIENT|FL_MONSTER)) && (head.classname!=self.classname))
  1255.          blowup = 1;
  1256.       if ((head.classname == self.classname) && (head.state==0))
  1257.          blowup = 1;
  1258.       traceline(self.origin,head.origin,TRUE,self);
  1259.       if (trace_fraction != 1.0)
  1260.          blowup = 0;
  1261.       if (blowup==1)
  1262.          {
  1263.          sound (self, CHAN_WEAPON, "hipweap/proxwarn.wav", 1, ATTN_NORM);
  1264.          ProximityGrenadeExplode();
  1265.          self.nextthink = time + 0.5;
  1266.          return;
  1267.          }
  1268.       head = head.chain;
  1269.       }
  1270.    self.nextthink = time + 0.25;
  1271.    };
  1272.  
  1273. /*
  1274. ================
  1275. W_FireProximityGrenade
  1276. ================
  1277. */
  1278. void() W_FireProximityGrenade =
  1279.    {
  1280.    local entity missile, mpuff;
  1281.  
  1282.    NumProximityGrenades = NumProximityGrenades + 1;
  1283.    self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  1284.  
  1285.    sound (self, CHAN_WEAPON, "hipweap/proxbomb.wav", 1, ATTN_NORM);
  1286.  
  1287.     self.punchangle_x = -2;
  1288.  
  1289.     missile = spawn ();
  1290.    missile.owner = self;
  1291.    missile.lastvictim = self;
  1292.    missile.movetype = MOVETYPE_TOSS;
  1293.     missile.solid = SOLID_BBOX;
  1294.    missile.classname = "proximity_grenade";
  1295.    missile.takedamage = DAMAGE_NO;
  1296.    missile.health = 5;
  1297.    missile.state = 0;
  1298.  
  1299. // set missile speed
  1300.  
  1301.     makevectors (self.v_angle);
  1302.  
  1303.     if (self.v_angle_x)
  1304.         missile.velocity = v_forward*600 + v_up * 200 + crandom()*v_right*10 + crandom()*v_up*10;
  1305.     else
  1306.     {
  1307.         missile.velocity = aim(self, 10000);
  1308.         missile.velocity = missile.velocity * 600;
  1309.         missile.velocity_z = 200;
  1310.     }
  1311.  
  1312.    missile.avelocity = '100 600 100';
  1313.  
  1314.     missile.angles = vectoangles(missile.velocity);
  1315.  
  1316.    missile.touch = ProximityGrenadeTouch;
  1317.  
  1318. // set missile duration
  1319.    missile.nextthink = time + 2;
  1320.    missile.delay = time + 15 + (10*random());
  1321.    missile.think = ProximityBomb;
  1322.    missile.th_die = ProximityGrenadeExplode;
  1323.  
  1324.    setmodel (missile, "progs/proxbomb.mdl");
  1325.    setorigin (missile, self.origin);
  1326.    setsize (missile, '-1 -1 -1', '1 1 1');
  1327.    };
  1328.  
  1329. //=============================================================================
  1330.  
  1331. void() spike_touch;
  1332. void() superspike_touch;
  1333.  
  1334.  
  1335. /*
  1336. ===============
  1337. launch_spike
  1338.  
  1339. Used for both the player and the ogre
  1340. ===============
  1341. */
  1342. void(vector org, vector dir) launch_spike =
  1343. {
  1344.     newmis = spawn ();
  1345.     newmis.owner = self;
  1346.     newmis.movetype = MOVETYPE_FLYMISSILE;
  1347.     newmis.solid = SOLID_BBOX;
  1348.  
  1349.     newmis.angles = vectoangles(dir);
  1350.  
  1351.     newmis.touch = spike_touch;
  1352.     newmis.classname = "spike";
  1353.     newmis.think = SUB_Remove;
  1354.     newmis.nextthink = time + 6;
  1355.     setmodel (newmis, "progs/spike.mdl");
  1356.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
  1357.     setorigin (newmis, org);
  1358.  
  1359.     newmis.velocity = dir * 1000;
  1360. };
  1361.  
  1362. void() W_FireSuperSpikes =
  1363. {
  1364.     local vector    dir;
  1365.     local entity    old;
  1366.  
  1367.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  1368.     self.attack_finished = time + 0.2;
  1369.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  1370.     dir = aim (self, 1000);
  1371.     launch_spike (self.origin + '0 0 16', dir);
  1372.     newmis.touch = superspike_touch;
  1373.     setmodel (newmis, "progs/s_spike.mdl");
  1374.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
  1375.     self.punchangle_x = -2;
  1376. };
  1377.  
  1378. void(float ox) W_FireSpikes =
  1379. {
  1380.     local vector    dir;
  1381.     local entity    old;
  1382.  
  1383.     makevectors (self.v_angle);
  1384.  
  1385.     if (self.ammo_nails >= 2 && self.weapon == IT_SUPER_NAILGUN)
  1386.     {
  1387.         W_FireSuperSpikes ();
  1388.         return;
  1389.     }
  1390.  
  1391.     if (self.ammo_nails < 1)
  1392.     {
  1393.         self.weapon = W_BestWeapon ();
  1394.         W_SetCurrentAmmo ();
  1395.         return;
  1396.     }
  1397.  
  1398.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  1399.     self.attack_finished = time + 0.2;
  1400.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  1401.     dir = aim (self, 1000);
  1402.     launch_spike (self.origin + '0 0 16' + v_right*ox, dir);
  1403.  
  1404.     self.punchangle_x = -2;
  1405. };
  1406.  
  1407.  
  1408.  
  1409. .float hit_z;
  1410. void() spike_touch =
  1411. {
  1412. local float rand;
  1413.     if (other == self.owner)
  1414.         return;
  1415.  
  1416.     if (other.solid == SOLID_TRIGGER)
  1417.         return;    // trigger field, do nothing
  1418.  
  1419.     if (pointcontents(self.origin) == CONTENT_SKY)
  1420.     {
  1421.         remove(self);
  1422.         return;
  1423.     }
  1424.  
  1425. // hit something that bleeds
  1426.     if (other.takedamage)
  1427.     {
  1428.         spawn_touchblood (9);
  1429.         T_Damage (other, self, self.owner, 9);
  1430.     }
  1431.     else
  1432.     {
  1433.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1434.  
  1435.         if (self.classname == "wizspike")
  1436.             WriteByte (MSG_BROADCAST, TE_WIZSPIKE);
  1437.         else if (self.classname == "knightspike")
  1438.             WriteByte (MSG_BROADCAST, TE_KNIGHTSPIKE);
  1439.         else
  1440.             WriteByte (MSG_BROADCAST, TE_SPIKE);
  1441.         WriteCoord (MSG_BROADCAST, self.origin_x);
  1442.         WriteCoord (MSG_BROADCAST, self.origin_y);
  1443.         WriteCoord (MSG_BROADCAST, self.origin_z);
  1444.     }
  1445.  
  1446.     remove(self);
  1447.  
  1448. };
  1449.  
  1450. void() superspike_touch =
  1451. {
  1452. local float rand;
  1453.     if (other == self.owner)
  1454.         return;
  1455.  
  1456.     if (other.solid == SOLID_TRIGGER)
  1457.         return;    // trigger field, do nothing
  1458.  
  1459.     if (pointcontents(self.origin) == CONTENT_SKY)
  1460.     {
  1461.         remove(self);
  1462.         return;
  1463.     }
  1464.  
  1465. // hit something that bleeds
  1466.     if (other.takedamage)
  1467.     {
  1468.         spawn_touchblood (18);
  1469.         T_Damage (other, self, self.owner, 18);
  1470.     }
  1471.     else
  1472.     {
  1473.         WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  1474.         WriteByte (MSG_BROADCAST, TE_SUPERSPIKE);
  1475.         WriteCoord (MSG_BROADCAST, self.origin_x);
  1476.         WriteCoord (MSG_BROADCAST, self.origin_y);
  1477.         WriteCoord (MSG_BROADCAST, self.origin_z);
  1478.     }
  1479.  
  1480.     remove(self);
  1481.  
  1482. };
  1483.  
  1484.  
  1485. /*
  1486. ===============================================================================
  1487.  
  1488. PLAYER WEAPON USE
  1489.  
  1490. ===============================================================================
  1491. */
  1492.  
  1493. //MED 10/18/96 added HIPWEAPONS
  1494. void() W_SetCurrentAmmo =
  1495. {
  1496.     player_run ();        // get out of any weapon firing states
  1497.  
  1498.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  1499.  
  1500.     if (self.weapon == IT_AXE)
  1501.     {
  1502.         self.currentammo = 0;
  1503.         self.weaponmodel = "progs/v_axe.mdl";
  1504.         self.weaponframe = 0;
  1505.     }
  1506. // Grapple:  Gotta fit this thing in somewhere...
  1507.         else if (self.weapon == IT_MORNINGSTAR)
  1508.         {
  1509.                 self.currentammo = 0;
  1510.                 self.weaponmodel = "progs/v_star.mdl";
  1511.                 self.weaponframe = 0;
  1512.         }
  1513. //===============================================
  1514.     else if (self.weapon == IT_SHOTGUN)
  1515.     {
  1516.         self.currentammo = self.ammo_shells;
  1517.         self.weaponmodel = "progs/v_shot.mdl";
  1518.         self.weaponframe = 0;
  1519.         self.items = self.items | IT_SHELLS;
  1520.     }
  1521.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1522.     {
  1523.         self.currentammo = self.ammo_shells;
  1524.         self.weaponmodel = "progs/v_shot2.mdl";
  1525.         self.weaponframe = 0;
  1526.         self.items = self.items | IT_SHELLS;
  1527.     }
  1528.     else if (self.weapon == IT_NAILGUN)
  1529.     {
  1530.         self.currentammo = self.ammo_nails;
  1531.         self.weaponmodel = "progs/v_nail.mdl";
  1532.         self.weaponframe = 0;
  1533.         self.items = self.items | IT_NAILS;
  1534.     }
  1535.     else if (self.weapon == IT_SUPER_NAILGUN)
  1536.     {
  1537.         self.currentammo = self.ammo_nails;
  1538.         self.weaponmodel = "progs/v_nail2.mdl";
  1539.         self.weaponframe = 0;
  1540.         self.items = self.items | IT_NAILS;
  1541.     }
  1542. //MED
  1543.    else if (self.weapon == IT_LASER_CANNON)
  1544.     {
  1545.         self.currentammo = self.ammo_cells;
  1546.       self.weaponmodel = "progs/v_laserg.mdl";
  1547.         self.weaponframe = 0;
  1548.         self.items = self.items | IT_CELLS;
  1549.     }
  1550.    else if (self.weapon == IT_GRENADE_LAUNCHER)
  1551.     {
  1552.         self.currentammo = self.ammo_rockets;
  1553.         self.weaponmodel = "progs/v_rock.mdl";
  1554.         self.weaponframe = 0;
  1555.         self.items = self.items | IT_ROCKETS;
  1556.     }
  1557.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1558.     {
  1559.         self.currentammo = self.ammo_rockets;
  1560.         self.weaponmodel = "progs/v_rock2.mdl";
  1561.         self.weaponframe = 0;
  1562.         self.items = self.items | IT_ROCKETS;
  1563.     }
  1564.     else if (self.weapon == IT_LIGHTNING)
  1565.     {
  1566.         self.currentammo = self.ammo_cells;
  1567.         self.weaponmodel = "progs/v_light.mdl";
  1568.         self.weaponframe = 0;
  1569.         self.items = self.items | IT_CELLS;
  1570.     }
  1571. //MED
  1572.    else if (self.weapon == IT_MJOLNIR)
  1573.     {
  1574.       self.currentammo = self.ammo_cells;
  1575.       self.weaponmodel = "progs/v_hammer.mdl";
  1576.         self.weaponframe = 0;
  1577.         self.items = self.items | IT_CELLS;
  1578.     }
  1579. //MED
  1580.    else if (self.weapon == IT_PROXIMITY_GUN)
  1581.     {
  1582.       self.currentammo = self.ammo_rockets;
  1583.       self.weaponmodel = "progs/v_prox.mdl";
  1584.         self.weaponframe = 0;
  1585.       self.items = self.items | IT_ROCKETS;
  1586.     }
  1587.    else
  1588.     {
  1589.         self.currentammo = 0;
  1590.         self.weaponmodel = "";
  1591.         self.weaponframe = 0;
  1592.     }
  1593. };
  1594.  
  1595. float() W_BestWeapon =
  1596. {
  1597.     local    float    it;
  1598.  
  1599.     it = self.items;
  1600.  
  1601.    if (self.waterlevel <= 1 && self.ammo_cells >= 1 && (it & IT_LIGHTNING) )
  1602.       return IT_LIGHTNING;
  1603. //MED
  1604.    else if(self.ammo_cells >= 1 && (it & IT_LASER_CANNON) )
  1605.       return IT_LASER_CANNON;
  1606.    else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  1607.         return IT_SUPER_NAILGUN;
  1608.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  1609.         return IT_SUPER_SHOTGUN;
  1610.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  1611.         return IT_NAILGUN;
  1612.     else if(self.ammo_shells >= 1 && (it & IT_SHOTGUN) )
  1613.         return IT_SHOTGUN;
  1614. //MED
  1615.    else if( it & IT_MJOLNIR )
  1616.       return IT_MJOLNIR;
  1617.  
  1618. /*
  1619.     if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  1620.         return IT_ROCKET_LAUNCHER;
  1621.     else if(self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
  1622.         return IT_GRENADE_LAUNCHER;
  1623.  
  1624. */
  1625.  
  1626.     return IT_AXE;
  1627. };
  1628.  
  1629. float() W_CheckNoAmmo =
  1630. {
  1631.     if (self.currentammo > 0)
  1632.         return TRUE;
  1633.  
  1634. // Grapple:  No ammo for grapple, either.
  1635.         if (self.weapon == IT_AXE || self.weapon == IT_MORNINGSTAR)
  1636.         return TRUE;
  1637.  
  1638. //MED
  1639.    if (self.weapon == IT_MJOLNIR)
  1640.       {
  1641.       return TRUE;
  1642.       }
  1643.  
  1644.    self.weapon = W_BestWeapon ();
  1645.  
  1646.     W_SetCurrentAmmo ();
  1647.  
  1648. // drop the weapon down
  1649.     return FALSE;
  1650. };
  1651.  
  1652. /*
  1653. ============
  1654. W_Attack
  1655.  
  1656. An attack impulse can be triggered now
  1657. ============
  1658. */
  1659. void()    player_axe1;
  1660. void()    player_axeb1;
  1661. void()    player_axec1;
  1662. void()    player_axed1;
  1663. void()    player_shot1;
  1664. void()    player_nail1;
  1665. void()    player_light1;
  1666. void()    player_rocket1;
  1667.  
  1668. // Grapple:  Declare chain functions, too!
  1669.  
  1670. void()    player_chain1;
  1671. void()  player_chain3;
  1672.  
  1673. //MED
  1674. void()   player_laser1;
  1675. void()   player_hammer1;
  1676. void()   player_mjolnir1;
  1677.  
  1678.  
  1679. void() W_Attack =
  1680. {
  1681.     local    float    r;
  1682.  
  1683.     if (!W_CheckNoAmmo ())
  1684.         return;
  1685.  
  1686.     makevectors    (self.v_angle);            // calculate forward angle for velocity
  1687.     self.show_hostile = time + 1;    // wake monsters up
  1688.  
  1689.     if (self.weapon == IT_AXE)
  1690.     {
  1691.         sound (self, CHAN_WEAPON, "weapons/ax1.wav", 1, ATTN_NORM);
  1692.         r = random();
  1693.         if (r < 0.25)
  1694.             player_axe1 ();
  1695.         else if (r<0.5)
  1696.             player_axeb1 ();
  1697.         else if (r<0.75)
  1698.             player_axec1 ();
  1699.         else
  1700.             player_axed1 ();
  1701.         self.attack_finished = time + 0.5;
  1702.     }
  1703.     else if (self.weapon == IT_SHOTGUN)
  1704.     {
  1705.         player_shot1 ();
  1706.         W_FireShotgun ();
  1707.         self.attack_finished = time + 0.5;
  1708.     }
  1709.     else if (self.weapon == IT_SUPER_SHOTGUN)
  1710.     {
  1711.         player_shot1 ();
  1712.         W_FireSuperShotgun ();
  1713.         self.attack_finished = time + 0.7;
  1714.     }
  1715.     else if (self.weapon == IT_NAILGUN)
  1716.     {
  1717.         player_nail1 ();
  1718.     }
  1719.     else if (self.weapon == IT_SUPER_NAILGUN)
  1720.     {
  1721.         player_nail1 ();
  1722.     }
  1723.     else if (self.weapon == IT_GRENADE_LAUNCHER)
  1724.     {
  1725.         player_rocket1();
  1726.         W_FireGrenade();
  1727.         self.attack_finished = time + 0.6;
  1728.     }
  1729.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  1730.     {
  1731.         player_rocket1();
  1732.         W_FireRocket();
  1733.         self.attack_finished = time + 0.8;
  1734.     }
  1735.     else if (self.weapon == IT_LIGHTNING)
  1736.     {
  1737.         player_light1();
  1738.         self.attack_finished = time + 0.1;
  1739.         sound (self, CHAN_AUTO, "weapons/lstart.wav", 1, ATTN_NORM);
  1740.     }
  1741. // Grapple:  Handle grapple attack.
  1742.         else if (self.weapon == IT_MORNINGSTAR)
  1743.         {
  1744.                 if (!self.hook_out)
  1745.                 {
  1746.                      player_chain1();
  1747.                 }
  1748.                 else {player_chain3();}
  1749.                 self.attack_finished = time + 0.5;
  1750.         }
  1751. //===============================================
  1752. //MED
  1753.    else if (self.weapon == IT_LASER_CANNON)
  1754.    {
  1755.       player_laser1();
  1756.    }
  1757. //MED
  1758.    else if (self.weapon == IT_MJOLNIR)
  1759.    {
  1760.       if (self.ammo_cells < 30)
  1761.          player_hammer1();
  1762.       else
  1763.          player_mjolnir1();
  1764.       self.attack_finished = time + 0.8;
  1765.    }
  1766. //MED
  1767.    else if (self.weapon == IT_PROXIMITY_GUN)
  1768.    {
  1769.       player_rocket1();
  1770.       W_FireProximityGrenade();
  1771.       self.attack_finished = time + 0.6;
  1772.    }
  1773. };
  1774.  
  1775. /*
  1776. ============
  1777. W_ChangeWeapon
  1778.  
  1779. ============
  1780. */
  1781. //MED 10/18/96 added hipweapons
  1782. void() W_ChangeWeapon =
  1783. {
  1784.     local    float    it, am, fl;
  1785.    local float oldimpulse;
  1786.  
  1787.     it = self.items;
  1788.     am = 0;
  1789.  
  1790. // Grapple:  Allow llamas who don't know how to bind impulses to use the grapple.
  1791.     if (self.impulse == 1)
  1792.     {
  1793.         if (self.weapon == IT_AXE) fl = IT_MORNINGSTAR;
  1794.                 else fl = IT_AXE;
  1795.     }
  1796. //===============================================
  1797. //MED
  1798.     else if (self.impulse == 2)
  1799.     {
  1800.         fl = IT_SHOTGUN;
  1801.         if (self.ammo_shells < 1)
  1802.             am = 1;
  1803.     }
  1804.     else if (self.impulse == 3)
  1805.     {
  1806.         fl = IT_SUPER_SHOTGUN;
  1807.         if (self.ammo_shells < 2)
  1808.             am = 1;
  1809.     }
  1810.     else if (self.impulse == 4)
  1811.     {
  1812.         fl = IT_NAILGUN;
  1813.         if (self.ammo_nails < 1)
  1814.             am = 1;
  1815.     }
  1816. //MED
  1817.     else if (self.impulse == 5)
  1818.     {
  1819.       fl = IT_SUPER_NAILGUN;
  1820.       if (self.ammo_nails < 2)
  1821.          am = 1;
  1822.  
  1823.     }
  1824. //MED
  1825.     else if (self.impulse == 6)
  1826.     {
  1827.       if (self.weapon == IT_GRENADE_LAUNCHER)
  1828.          {
  1829.          fl = IT_PROXIMITY_GUN;
  1830.          }
  1831.       else
  1832.          {
  1833.          fl = IT_GRENADE_LAUNCHER;
  1834.          }
  1835.         if (self.ammo_rockets < 1)
  1836.             am = 1;
  1837.     }
  1838.     else if (self.impulse == 7)
  1839.     {
  1840.         fl = IT_ROCKET_LAUNCHER;
  1841.         if (self.ammo_rockets < 1)
  1842.             am = 1;
  1843.     }
  1844. //MED
  1845.     else if (self.impulse == 8)
  1846.     {
  1847.       fl = IT_LIGHTNING;
  1848.       if (self.ammo_cells < 1)
  1849.          am = 1;
  1850.    }
  1851. // Grapple:  ... And an impulse for the Quakers.
  1852.         else if (self.impulse == 21)
  1853.                 fl = IT_MORNINGSTAR;
  1854. //===============================================
  1855.    else if (self.impulse == 225)
  1856.     {
  1857.       fl = IT_LASER_CANNON;
  1858.       if (self.ammo_cells < 1)
  1859.          am = 1;
  1860.    }
  1861.    else if (self.impulse == 226)
  1862.     {
  1863.       fl = IT_MJOLNIR;
  1864.    }
  1865.  
  1866. //MED
  1867.    oldimpulse = self.impulse;
  1868.     self.impulse = 0;
  1869.  
  1870.     if (!(self.items & fl))
  1871.       {
  1872. //MED
  1873.       if (fl == IT_GRENADE_LAUNCHER)
  1874.          {
  1875.          fl = IT_PROXIMITY_GUN;
  1876.          if (!(self.items & fl))
  1877.             {
  1878.             sprint (self, "no weapon.\n");
  1879.             return;
  1880.             }
  1881.          if (self.ammo_rockets < 1)
  1882.             am = 1;
  1883.          else
  1884.             am = 0;
  1885.          }
  1886.       else
  1887.          {
  1888.          sprint (self, "no weapon.\n");
  1889.          return;
  1890.          }
  1891.       }
  1892.  
  1893.     if (am)
  1894.     {    // don't have the ammo
  1895.         sprint (self, "not enough ammo.\n");
  1896.         return;
  1897.     }
  1898.  
  1899. //
  1900. // set weapon, set ammo
  1901. //
  1902.    self.weapon = fl;
  1903.     W_SetCurrentAmmo ();
  1904. };
  1905.  
  1906. /*
  1907. ============
  1908. CheatCommand
  1909. ============
  1910. */
  1911. void() CheatCommand =
  1912. {
  1913.     if (deathmatch || coop)
  1914.         return;
  1915.  
  1916.     self.ammo_rockets = 100;
  1917.     self.ammo_nails = 200;
  1918.     self.ammo_shells = 100;
  1919.     self.items = self.items |
  1920.         IT_AXE |
  1921.         IT_SHOTGUN |
  1922.         IT_SUPER_SHOTGUN |
  1923.         IT_NAILGUN |
  1924.         IT_SUPER_NAILGUN |
  1925.         IT_GRENADE_LAUNCHER |
  1926.         IT_ROCKET_LAUNCHER |
  1927.         IT_KEY1 | IT_KEY2;
  1928.  
  1929.     self.ammo_cells = 200;
  1930.     self.items = self.items | IT_LIGHTNING;
  1931. //MED
  1932.    self.items = self.items | IT_LASER_CANNON;
  1933.    self.items = self.items | IT_MJOLNIR;
  1934.    self.items = self.items | IT_PROXIMITY_GUN;
  1935.  
  1936.     self.weapon = IT_ROCKET_LAUNCHER;
  1937.     self.impulse = 0;
  1938.     W_SetCurrentAmmo ();
  1939. };
  1940.  
  1941. /*
  1942. ============
  1943. CycleWeaponCommand
  1944.  
  1945. Go to the next weapon with ammo
  1946. ============
  1947. */
  1948. void() CycleWeaponCommand =
  1949. {
  1950.     local    float    it, am;
  1951.  
  1952.     it = self.items;
  1953.     self.impulse = 0;
  1954.  
  1955.     while (1)
  1956.     {
  1957.         am = 0;
  1958.  
  1959. //MED
  1960.       if (self.weapon == IT_MJOLNIR)
  1961.         {
  1962.             self.weapon = IT_AXE;
  1963.         }
  1964.         else if (self.weapon == IT_AXE)
  1965. // Grapple:  Install the grappling hook in the switch command.
  1966.                 {
  1967.                         self.weapon = IT_MORNINGSTAR;
  1968.                 }
  1969.                 else if (self.weapon == IT_MORNINGSTAR)
  1970. //===============================================
  1971.         {
  1972.          self.weapon = IT_SHOTGUN;
  1973.          if (self.ammo_shells < 1)
  1974.                 am = 1;
  1975.       }
  1976.       else if (self.weapon == IT_SHOTGUN)
  1977.         {
  1978.             self.weapon = IT_SUPER_SHOTGUN;
  1979.             if (self.ammo_shells < 2)
  1980.                 am = 1;
  1981.         }
  1982.         else if (self.weapon == IT_SUPER_SHOTGUN)
  1983.         {
  1984.             self.weapon = IT_NAILGUN;
  1985.             if (self.ammo_nails < 1)
  1986.                 am = 1;
  1987.         }
  1988.         else if (self.weapon == IT_NAILGUN)
  1989.         {
  1990.             self.weapon = IT_SUPER_NAILGUN;
  1991.             if (self.ammo_nails < 2)
  1992.                 am = 1;
  1993.         }
  1994.         else if (self.weapon == IT_SUPER_NAILGUN)
  1995.         {
  1996.          self.weapon = IT_GRENADE_LAUNCHER;
  1997.             if (self.ammo_rockets < 1)
  1998.                 am = 1;
  1999.         }
  2000. //MED
  2001.       else if (self.weapon == IT_GRENADE_LAUNCHER)
  2002.         {
  2003.          self.weapon = IT_PROXIMITY_GUN;
  2004.             if (self.ammo_rockets < 1)
  2005.                 am = 1;
  2006.         }
  2007. //MED
  2008.       else if (self.weapon == IT_PROXIMITY_GUN)
  2009.         {
  2010.             self.weapon = IT_ROCKET_LAUNCHER;
  2011.             if (self.ammo_rockets < 1)
  2012.                 am = 1;
  2013.         }
  2014.       else if (self.weapon == IT_ROCKET_LAUNCHER)
  2015.         {
  2016.             self.weapon = IT_LIGHTNING;
  2017.             if (self.ammo_cells < 1)
  2018.                 am = 1;
  2019.         }
  2020.       else if (self.weapon == IT_LIGHTNING)
  2021.         {
  2022.          self.weapon = IT_LASER_CANNON;
  2023.          if (self.ammo_cells < 1)
  2024.                 am = 1;
  2025.         }
  2026.       else if (self.weapon == IT_LASER_CANNON)
  2027.         {
  2028.          self.weapon = IT_MJOLNIR;
  2029.         }
  2030.  
  2031.         if ( (self.items & self.weapon) && am == 0)
  2032.         {
  2033.             W_SetCurrentAmmo ();
  2034.             return;
  2035.         }
  2036.     }
  2037.  
  2038. };
  2039.  
  2040. /*
  2041. ============
  2042. CycleWeaponReverseCommand
  2043.  
  2044. Go to the prev weapon with ammo
  2045. ============
  2046. */
  2047. void() CycleWeaponReverseCommand =
  2048. {
  2049.     local    float    it, am;
  2050.  
  2051.     it = self.items;
  2052.     self.impulse = 0;
  2053.  
  2054.     while (1)
  2055.     {
  2056.         am = 0;
  2057.  
  2058. //MED
  2059.       if (self.weapon == IT_MJOLNIR)
  2060.         {
  2061.          self.weapon = IT_LASER_CANNON;
  2062.          if (self.ammo_cells < 1)
  2063.                 am = 1;
  2064.         }
  2065. //MED
  2066.       else if (self.weapon == IT_LASER_CANNON)
  2067.         {
  2068.          self.weapon = IT_LIGHTNING;
  2069.          if (self.ammo_cells < 1)
  2070.                 am = 1;
  2071.         }
  2072.       else if (self.weapon == IT_LIGHTNING)
  2073.         {
  2074.             self.weapon = IT_ROCKET_LAUNCHER;
  2075.             if (self.ammo_rockets < 1)
  2076.                 am = 1;
  2077.         }
  2078.       else if (self.weapon == IT_ROCKET_LAUNCHER)
  2079.         {
  2080.          self.weapon = IT_PROXIMITY_GUN;
  2081.             if (self.ammo_rockets < 1)
  2082.                 am = 1;
  2083.         }
  2084.       else if (self.weapon == IT_PROXIMITY_GUN)
  2085.         {
  2086.             self.weapon = IT_GRENADE_LAUNCHER;
  2087.             if (self.ammo_rockets < 1)
  2088.                 am = 1;
  2089.         }
  2090.       else if (self.weapon == IT_GRENADE_LAUNCHER)
  2091.         {
  2092.             self.weapon = IT_SUPER_NAILGUN;
  2093.             if (self.ammo_nails < 2)
  2094.                 am = 1;
  2095.         }
  2096.       else if (self.weapon == IT_SUPER_NAILGUN)
  2097.         {
  2098.             self.weapon = IT_NAILGUN;
  2099.             if (self.ammo_nails < 1)
  2100.                 am = 1;
  2101.         }
  2102.         else if (self.weapon == IT_NAILGUN)
  2103.         {
  2104.             self.weapon = IT_SUPER_SHOTGUN;
  2105.             if (self.ammo_shells < 2)
  2106.                 am = 1;
  2107.         }
  2108.         else if (self.weapon == IT_SUPER_SHOTGUN)
  2109.         {
  2110.             self.weapon = IT_SHOTGUN;
  2111.             if (self.ammo_shells < 1)
  2112.                 am = 1;
  2113.         }
  2114.         else if (self.weapon == IT_SHOTGUN)
  2115. // Grapple:  Here, too.
  2116.                 {
  2117.                         self.weapon = IT_MORNINGSTAR;
  2118.                 }
  2119.                 else if (self.weapon == IT_MORNINGSTAR)
  2120. //===============================================
  2121.         {
  2122.             self.weapon = IT_AXE;
  2123.         }
  2124.         else if (self.weapon == IT_AXE)
  2125.         {
  2126.          self.weapon = IT_MJOLNIR;
  2127.         }
  2128.  
  2129.         if ( (it & self.weapon) && am == 0)
  2130.         {
  2131.             W_SetCurrentAmmo ();
  2132.             return;
  2133.         }
  2134.     }
  2135.  
  2136. };
  2137.  
  2138. /*
  2139. ============
  2140. ServerflagsCommand
  2141.  
  2142. Just for development
  2143. ============
  2144. */
  2145. void() ServerflagsCommand =
  2146. {
  2147.     serverflags = serverflags * 2 + 1;
  2148. };
  2149.  
  2150. void() QuadCheat =
  2151. {
  2152.     if (deathmatch || coop)
  2153.         return;
  2154.     self.super_time = 1;
  2155.     self.super_damage_finished = time + 30;
  2156.     self.items = self.items | IT_QUAD;
  2157.    bprint ("quad cheat\n");
  2158. };
  2159.  
  2160. //MED
  2161. void() WetsuitCheat =
  2162.     {
  2163.    if (deathmatch || coop)
  2164.         return;
  2165.    self.items2 = self.items2 | HIP_IT_WETSUIT;
  2166.     self.wetsuit_time = 1;
  2167.     self.wetsuit_finished = time + 30;
  2168.    bprint( "wetsuit cheat\n" );
  2169.     };
  2170.  
  2171. //MED
  2172. void() EmpathyShieldsCheat =
  2173.     {
  2174.    if (deathmatch || coop)
  2175.         return;
  2176.    self.items2 = self.items2 | HIP_IT_EMPATHY_SHIELDS;
  2177.    self.empathy_time = 1;
  2178.    self.empathy_finished = time + 30;
  2179.    bprint( "empathy shields cheat\n" );
  2180.     };
  2181.  
  2182. void() DumpEntities =
  2183.    {
  2184.    local entity   head;
  2185.    local float i;
  2186.  
  2187.    i = 1;
  2188.    head = nextent(world);
  2189.    while (head!=world)
  2190.       {
  2191.       dprint(ftos(i));
  2192.       dprint(" ");
  2193.       dprint(head.classname);
  2194.       dprint("\n");
  2195.       head = nextent(head);
  2196.       i = i + 1;
  2197.       }
  2198.    };
  2199.  
  2200. void() DumpLiveEntities =
  2201.    {
  2202.    local entity   head;
  2203.    local float i;
  2204.  
  2205.    i = 1;
  2206.    head = nextent(world);
  2207.    while (head!=world)
  2208.       {
  2209.       if (head.health > 0)
  2210.          {
  2211.          dprint(ftos(i));
  2212.          dprint(" ");
  2213.          dprint(head.classname);
  2214.          dprint(" ");
  2215.          dprint(vtos(head.origin));
  2216.          dprint("\n");
  2217.          dprint("--------------------\n");
  2218.          }
  2219.       head = nextent(head);
  2220.       i = i + 1;
  2221.       }
  2222.    };
  2223.  
  2224. void() Genocide =
  2225.    {
  2226.    local entity   head;
  2227.  
  2228.    if (deathmatch || coop)
  2229.         return;
  2230.    bprint("Genocide!\n");
  2231.    head = nextent(world);
  2232.    while (head!=world)
  2233.       {
  2234.       if ((head.health > 0) && (head.flags & FL_MONSTER))
  2235.          {
  2236.          T_Damage(head,world,world,head.health+10);
  2237.          }
  2238.       head = nextent(head);
  2239.       }
  2240.    };
  2241.  
  2242. float dump_coord;
  2243. void () ToggleDump =
  2244.    {
  2245.    dump_coord = 1 - dump_coord;
  2246.    if (dump_coord == 1)
  2247.       bprint("Dumping Player Location\n");
  2248.    };
  2249. void () DumpCoordinates =
  2250.    {
  2251.    local entity pl;
  2252.    pl = checkclient();
  2253.    if (pl)
  2254.       {
  2255.       bprint("Player: ");
  2256.       bprint(vtos(pl.origin));
  2257.       bprint("\n");
  2258.       }
  2259.    };
  2260. /*
  2261. ============
  2262. ImpulseCommands
  2263.  
  2264. ============
  2265. */
  2266. void() ImpulseCommands =
  2267. {
  2268.     if (self.impulse >= 1 && self.impulse <= 8)
  2269.         W_ChangeWeapon ();
  2270.  
  2271.    if (self.impulse >= 225 && self.impulse <= 226)
  2272.         W_ChangeWeapon ();
  2273.  
  2274.     if (self.impulse == 9)
  2275.         CheatCommand ();
  2276.    if (self.impulse == 10)
  2277.         CycleWeaponCommand ();
  2278.     if (self.impulse == 11)
  2279.         ServerflagsCommand ();
  2280.     if (self.impulse == 12)
  2281.         CycleWeaponReverseCommand ();
  2282. // Grapple:  Switch to the hook on impulse
  2283.         if (self.impulse == 21)
  2284.                 W_ChangeWeapon();
  2285.         if (self.impulse == 112)
  2286.         {
  2287.                 sprint (self,"Program by Tatter_D!\n");
  2288.                 sound (self, CHAN_AUTO, "weapons/thankyou.wav", 1,
  2289.                         ATTN_STATIC);
  2290.                 sprint (self,"Grafted for SOA by Kiwi\n");
  2291.         }
  2292. //===============================================
  2293. //JIM
  2294.     if ( self.impulse == 200 )
  2295.         WetsuitCheat();
  2296. //MED
  2297.    if ( self.impulse == 201 )
  2298.       EmpathyShieldsCheat();
  2299.    if ( self.impulse == 205 )
  2300.       Genocide();
  2301.    if ( self.impulse == 206 )
  2302.       ToggleDump();
  2303.    if ( self.impulse == 202 )
  2304.       DumpEntities();
  2305.    if ( self.impulse == 203 )
  2306.       DumpLiveEntities();
  2307.    if (self.impulse == 255)
  2308.         QuadCheat ();
  2309.    if (dump_coord == 1)
  2310.       DumpCoordinates();
  2311.  
  2312.     self.impulse = 0;
  2313. };
  2314.  
  2315. /*
  2316. ============
  2317. W_WeaponFrame
  2318.  
  2319. Called every frame so impulse events can be handled as well as possible
  2320. ============
  2321. */
  2322. void() W_WeaponFrame =
  2323. {
  2324.     if (time < self.attack_finished)
  2325.         return;
  2326.  
  2327.     ImpulseCommands ();
  2328.  
  2329. // check for attack
  2330.     if (self.button0)
  2331.     {
  2332.         SuperDamageSound ();
  2333.         W_Attack ();
  2334.     }
  2335. };
  2336.  
  2337. /*
  2338. ========
  2339. SuperDamageSound
  2340.  
  2341. Plays sound if needed
  2342. ========
  2343. */
  2344. void() SuperDamageSound =
  2345. {
  2346.     if (self.super_damage_finished > time)
  2347.     {
  2348.         if (self.super_sound < time)
  2349.         {
  2350.             self.super_sound = time + 1;
  2351.             sound (self, CHAN_BODY, "items/damage3.wav", 1, ATTN_NORM);
  2352.         }
  2353.     }
  2354.     return;
  2355. };
  2356.